package com.bxs.detector.impl;

import com.bxs.detector.BaseDetector;
import com.bxs.pojo.BaseRule;
import com.bxs.pojo.DangerMsg;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.pcap4j.core.PcapPacket;
import org.pcap4j.packet.IcmpV4CommonPacket;
import org.pcap4j.packet.IpPacket;
import org.pcap4j.packet.Packet;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.Map;

// ICMP数据报检测(网际层数据报检测)
@Component
public class ICMPPacketDetector extends BaseDetector {
    @Override
    public DangerMsg detect(PcapPacket packet, List<BaseRule> rules) throws JsonProcessingException, UnsupportedEncodingException {
        // 解析为ICMP数据报
        IcmpV4CommonPacket pack = packet.get(IcmpV4CommonPacket.class);
        if(pack == null)return null;
        // 字段检测
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println("start ICMPv4PacketDetector" + rules);
        // 规则数量较少则直接检测
        for(BaseRule rule : rules){
            String protocolType = rule.getProtocolType();
            if (!protocolType.equals("ICMPv4"))continue;                                     // 不是ICMP报文的规则交给其他的处理
            // 获取规则中的字段匹配值
            String protocolFields = rule.getProtocolFields() == null ? "{}" : rule.getProtocolFields();
            Map<String, String> map = objectMapper.readValue(protocolFields, Map.class);
            boolean pass = true;
            // 检测IP首部字段
            // icmp报文类型
            if (map.containsKey("type") && pack.getHeader().getType().valueAsString().equals(map.get("type"))){
                continue;
            }else if (map.containsKey("code") && pack.getHeader().getCode().valueAsString().equals(map.get("code"))){
                // 协议类型不一致
                continue;
            }
            // 检查主体数据
            if (!rule.text.trim().equals("")){
                byte[] rawData = pack.getRawData();
                String packetData = new String(rawData, "UTF-8");
                if (packetData.indexOf(rule.getText()) != -1){
                    // 所有条件均符合
                    DangerMsg dangerMsg = new DangerMsg();
                    dangerMsg.setPacket(packet);
                    dangerMsg.setCode(rule.getLevel());
                    IpPacket ipPacket = packet.get(IpPacket.class);
                    dangerMsg.setSourceIp(ipPacket.getHeader().getSrcAddr().getHostName());
                    dangerMsg.setTargetIp(ipPacket.getHeader().getDstAddr().getHostName());
                    dangerMsg.setDate(new Date());
                    dangerMsg.setDesc(rule.getMsg());
                    return dangerMsg;
                }
            }
        }
        return null;
    }
}
